You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The issue is that debug_traceTransaction was computing the upfront gas fee as gasLimit × gasPrice (the raw field),
which for EIP-1559 txs can be much higher than what was actually charged on-chain.
The fix computes the correct effective gas price (min(baseFee + gasTipCap, gasFeeCap)) — matching what geth's state
transition actually charges — and performs the deduction at the EVM stateDB level rather than going through the bank
module's spendable balance check. This means the trace will always succeed as long as the original tx succeeded
on-chain.
PR Review: fix(evm): align debug_trace fee with virtual ante path
Gather context and understand the request
Read changed files
Analyze code changes
Post review feedback
Summary
The overall direction is correct — replacing the raw StateDB.SubBalance/AddBalance with DeductTxCostsFromUserBalance + RefundGas aligns the debug trace path with the virtual fee collector approach used in CheckEthGasConsume / ApplyTransaction. The BaseFee.BigInt() fix in TraceTx is a clean correctness improvement.
One significant bug was found, plus a few smaller concerns:
Issues Found
🔴 Deduct/Refund Price Asymmetry (EIP-1559)
debugTraceFeeAmount (in utils.go) correctly computes the effective gas price as min(tip+baseFee, feeCap), so the deduction uses the right amount. However, RefundGas (in gas.go:52) computes the refund as leftoverGas * msg.GasPrice — and for EIP-1559 transactions, msg.GasPrice is set to GasFeeCap by core.TransactionToMessage.
For a tx with baseFee=1gwei, tip=0, feeCap=5000gwei, gasLimit=2M, leftoverGas=1M:
The test masks this because gasTipCap=0 makes effectiveGasPrice == baseFee, so both sides use the same value. See inline comments for details.
🟡 Test Setup Ordering (state_transition_test.go:670)
SetupTestWithCb is called then immediately overridden by SetupTest. Whether the callback actually takes effect depends on internal test suite wiring — worth a double-check.
🟡 Nonce Semantics for Contract Creation in DebugTrace (state_transition.go:367)
The nonce is incremented eagerly on line 367 for all DebugTrace calls (including contractCreation). The Create branch later resets the nonce to msg.Nonce (line 444), which would undo the increment. This was the same in the old code, but worth documenting that the nonce reset in Create handles this.
🟢 Missing CHANGELOG Entry
The bot already flagged this. An entry under ## Unreleased like:
* (rpc) [#967](https://github.com/crypto-org-chain/ethermint/pull/967) fix(evm): align debug_traceTransaction fee deduction with virtual ante path (EIP-1559 effective gas price, BigInt BaseFee parse).
🟢 No Breaking State Changes
This PR only affects the debug_trace* RPC path (no ante handler, no consensus, no state serialization changes). It is not a state-breaking change and is safe to merge to a release branch from a consensus perspective.
Verdict
The core issue being fixed is real and the approach is right. The EIP-1559 refund asymmetry should be resolved before merge — it would cause RefundGas to fail or over-refund whenever gasFeeCap > effectiveGasPrice (which is the common case for EIP-1559 txs). All inline comments have been posted above.
❌ Patch coverage is 87.09677% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.88%. Comparing base (30214c2) to head (96731ac).
PR Review: fix(evm): align debug_trace fee with virtual ante path
Gather context and understand the request
Read changed files
Analyze code changes
Post review feedback
Summary
The fix is correct and the previous review's top concern (deduct/refund price asymmetry) has been addressed. Here's the full picture:
Key Changes and Assessment
x/evm/keeper/utils.go — New helper functions ✅
debugTraceGasPrice correctly computes min(tip + baseFee, feeCap) for EIP-1559 and falls back to msg.GasPrice for legacy txs. debugTraceFeeAmount multiplies by gasLimit. Both are well-named and isolated.
The previous review's concern about RefundGas asymmetry no longer applies — the debug trace path bypasses RefundGas entirely and handles the refund inline with the correct price. Net deduction = effectiveGasPrice × gasUsed, matching on-chain behavior exactly.
The removal of the debugFn closure (previously deferred, now inline) also eliminates a subtle ordering hazard: the old code could call the deferred debugFn after the OnTxEnd tracer callback, which had the wrong gas accounting.
x/evm/keeper/gas.go — RefundGasWithPrice ✅
Clean refactor: RefundGas now delegates to RefundGasWithPrice. The new function is not called from the debug trace path (which uses stateDB.AddBalance directly), but it's a valid separation for other callers. No issues.
Replacing big.NewInt(req.BaseFee.Int64()) with req.BaseFee.BigInt() avoids silent truncation for baseFees > math.MaxInt64. The added !req.BaseFee.IsNil() guard is correct. Minor: sdkmath.Int.BigInt() returns a copy, so no defensive copying is needed by the caller — this is already the case.
Issues Found
🟡 Redundant SetupTestWithCb call in test (state_transition_test.go:664)
suite.SetupTestWithCb(t, func(...) { ...NoBaseFee=false ... }) // ← this init is discardedsuite.mintFeeCollector=truesuite.SetupTest() // ← this reinitializes from scratch with NoBaseFee = true
The first SetupTestWithCb at line 664 fully initializes the app with NoBaseFee=false, but the SetupTest() call at line 672 immediately reinitializes it (with NoBaseFee=true). The fee market configuration from the first call is discarded entirely. The test still works because cfg.BaseFee = baseFee is set manually on line 697, bypassing the module state.
The intent appears to be testing with an active base fee, but the module is actually initialized with NoBaseFee=true. The test validates the right thing (effective price deduction), but the setup is misleading. Consider restructuring:
// Correct: set mintFeeCollector before SetupTest so the callback reads itsuite.mintFeeCollector=truesuite.SetupTestWithCb(t, func(a*evmd.EthermintApp, genesis evmd.GenesisState) evmd.GenesisState {
feemarketGenesis:=feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight=1feemarketGenesis.Params.NoBaseFee=falsegenesis[feemarkettypes.ModuleName] =a.AppCodec().MustMarshalJSON(feemarketGenesis)
// ... fee collector minting ...returngenesis
})
🟡 Test only covers gasTipCap=0 (same as previous review)
With gasTipCap=0, effectiveGasPrice == baseFee, so deduction and refund both operate on the same value even without the fix. A complementary case with gasTipCap > 0 and gasFeeCap >> baseFee + tip would more directly validate the asymmetry was fixed. Since the refund path (debugTraceGasPrice) uses the same min(tip+baseFee, feeCap) formula as the deduction, the code is correct for all cases — but the test coverage gap is worth noting.
🟢 No state-breaking changes
This PR only modifies the debug_trace* RPC path. No ante handler, no consensus logic, no state serialization changes. Safe to merge to a release branch.
Verdict
The core fix is correct. The EIP-1559 refund asymmetry from the previous review has been resolved. The two remaining points above are minor code quality issues — the test redundancy is cosmetic and doesn't affect correctness. The PR is ready to merge once the test setup is cleaned up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #XXX
Description
The issue is that debug_traceTransaction was computing the upfront gas fee as gasLimit × gasPrice (the raw field),
which for EIP-1559 txs can be much higher than what was actually charged on-chain.
The fix computes the correct effective gas price (min(baseFee + gasTipCap, gasFeeCap)) — matching what geth's state
transition actually charges — and performs the deduction at the EVM stateDB level rather than going through the bank
module's spendable balance check. This means the trace will always succeed as long as the original tx succeeded
on-chain.
For contributor use:
docs/) or specification (x/<module>/spec/)godoccomments.Unreleasedsection inCHANGELOG.mdFiles changedin the Github PR explorerFor admin use:
WIP,R4R,docs, etc)